/**
 * 
 * @brief  bsp_net.c
 * @param  None
 * 
 * @author xhq
 * @date   2024/11/05
 * 
 */
/* include */
#include "bsp_net.h"
#include "util_factory.h"

/* define */
#define BSP_NET_DEBUG       0

/* typedef */

/* function */
/**
 * @brief 网络模块初始化
 * 
 * @param None ：
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
uint32_t net_modules_init()
{
    uint32_t l_u32_ret = 0;
    
    /* phy init */
    // 这里可能需要对phy芯片的一个引脚拉高拉低（复位）一下，保证网口千兆的带宽速率

    // cat /sys/class/net/eth0/speed 获取网卡连接速度


    /* 广播IPv4/IPv6 ip socket convert */
    if (ipv4_ipv6_ip_socket_init(SOCKET_BROADCAST_TYPE) != 0)
    {
        SET_ERROR_CODE(l_u32_ret, 0);
        goto error;
    }
    /* init udp broadcast socket */
    if (socket_modules_init(&g_socket_info[SOCKET_BROADCAST_TYPE]) != 0)
    {
        SET_ERROR_CODE(l_u32_ret, 1);
        goto error;
    }

    /* cmd IPv4/IPv6 ip socket convert */
    if (ipv4_ipv6_ip_socket_init(SOCKET_CMD_TYPE) != 0)
    {
        SET_ERROR_CODE(l_u32_ret, 2);
        goto error;
    }
    /* init udp cmd socket */
    if (socket_modules_init(&g_socket_info[SOCKET_CMD_TYPE]) != 0)
    {
        SET_ERROR_CODE(l_u32_ret, 3);
        goto error;
    }

    /* init udp data socket */


    error:
    RETURN_ERROR_CODE(l_u32_ret, __func__);
}
/**
 * @brief get param from ini file
 * 
 * @param ini_net_info ：ini网络参数信息结构体
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
uint32_t get_net_param_from_ini(ini_net_info_type *ini_net_info)
{
    uint32_t l_u32_ret = 0;
    uint8_t l_pu8_temp_buf[16] = {0};   // 针对ipv6地址，避免使用指针，sscanf函数会修改后一个结构体成员的值
    int32_t l_i32_i = 0;

    // 建议这里每次完成一个字段的取值后，清空下l_pu8_temp_buf中的值

    // ipv4
    /* 解析参数 */
    g_net_info.ip4_local_ip = inet_addr(ini_net_info->ip4_local_ip.v.s);
    g_net_info.ip4_dest_ip = inet_addr(ini_net_info->ip4_dest_ip.v.s);
    sscanf(ini_net_info->ip4_mask.v.s, "%hhd.%hhd.%hhd.%hhd", &l_pu8_temp_buf[0], &l_pu8_temp_buf[1], &l_pu8_temp_buf[2], &l_pu8_temp_buf[3]);
    memcpy((uint8_t *)&g_net_info.ip4_mask[0], &l_pu8_temp_buf, sizeof(g_net_info.ip4_mask));
    sscanf(ini_net_info->ip4_gateway.v.s, "%hhd.%hhd.%hhd.%hhd", &l_pu8_temp_buf[0], &l_pu8_temp_buf[1], &l_pu8_temp_buf[2], &l_pu8_temp_buf[3]);
    memcpy((uint8_t *)&g_net_info.ip4_gateway[0], &l_pu8_temp_buf, sizeof(g_net_info.ip4_gateway));

    // ipv6 
    sscanf((uint8_t *)ini_net_info->ip_local_ipv6.v.s, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", 
        &l_pu8_temp_buf[0],&l_pu8_temp_buf[1],&l_pu8_temp_buf[2],&l_pu8_temp_buf[3],
        &l_pu8_temp_buf[4],&l_pu8_temp_buf[5],&l_pu8_temp_buf[6],&l_pu8_temp_buf[7],
        &l_pu8_temp_buf[8],&l_pu8_temp_buf[9],&l_pu8_temp_buf[10],&l_pu8_temp_buf[11],
        &l_pu8_temp_buf[12],&l_pu8_temp_buf[13],&l_pu8_temp_buf[14],&l_pu8_temp_buf[15]);
    memcpy((uint8_t *)&g_net_info.ip6_local_ip[0], &l_pu8_temp_buf, sizeof(g_net_info.ip6_local_ip));

    sscanf((uint8_t *)ini_net_info->ip_global_ipv6.v.s, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", 
        &l_pu8_temp_buf[0],&l_pu8_temp_buf[1],&l_pu8_temp_buf[2],&l_pu8_temp_buf[3],
        &l_pu8_temp_buf[4],&l_pu8_temp_buf[5],&l_pu8_temp_buf[6],&l_pu8_temp_buf[7],
        &l_pu8_temp_buf[8],&l_pu8_temp_buf[9],&l_pu8_temp_buf[10],&l_pu8_temp_buf[11],
        &l_pu8_temp_buf[12],&l_pu8_temp_buf[13],&l_pu8_temp_buf[14],&l_pu8_temp_buf[15]);
    memcpy((uint8_t *)&g_net_info.ip6_global_ip[0], &l_pu8_temp_buf, sizeof(g_net_info.ip6_global_ip));

    sscanf((uint8_t *)ini_net_info->ip_ipv6.v.s, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", 
        &l_pu8_temp_buf[0],&l_pu8_temp_buf[1],&l_pu8_temp_buf[2],&l_pu8_temp_buf[3],
        &l_pu8_temp_buf[4],&l_pu8_temp_buf[5],&l_pu8_temp_buf[6],&l_pu8_temp_buf[7],
        &l_pu8_temp_buf[8],&l_pu8_temp_buf[9],&l_pu8_temp_buf[10],&l_pu8_temp_buf[11],
        &l_pu8_temp_buf[12],&l_pu8_temp_buf[13],&l_pu8_temp_buf[14],&l_pu8_temp_buf[15]);
    memcpy((uint8_t *)&g_net_info.ip6_dest_ip[0], &l_pu8_temp_buf, sizeof(g_net_info.ip6_dest_ip));

    sscanf((uint8_t *)ini_net_info->mask_ipv6.v.s, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", 
        &l_pu8_temp_buf[0],&l_pu8_temp_buf[1],&l_pu8_temp_buf[2],&l_pu8_temp_buf[3],
        &l_pu8_temp_buf[4],&l_pu8_temp_buf[5],&l_pu8_temp_buf[6],&l_pu8_temp_buf[7],
        &l_pu8_temp_buf[8],&l_pu8_temp_buf[9],&l_pu8_temp_buf[10],&l_pu8_temp_buf[11],
        &l_pu8_temp_buf[12],&l_pu8_temp_buf[13],&l_pu8_temp_buf[14],&l_pu8_temp_buf[15]);
    memcpy((uint8_t *)&g_net_info.ip6_mask[0], &l_pu8_temp_buf, sizeof(g_net_info.ip6_mask));

    sscanf((uint8_t *)ini_net_info->gateway_ipv6.v.s, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", 
        &l_pu8_temp_buf[0],&l_pu8_temp_buf[1],&l_pu8_temp_buf[2],&l_pu8_temp_buf[3],
        &l_pu8_temp_buf[4],&l_pu8_temp_buf[5],&l_pu8_temp_buf[6],&l_pu8_temp_buf[7],
        &l_pu8_temp_buf[8],&l_pu8_temp_buf[9],&l_pu8_temp_buf[10],&l_pu8_temp_buf[11],
        &l_pu8_temp_buf[12],&l_pu8_temp_buf[13],&l_pu8_temp_buf[14],&l_pu8_temp_buf[15]);
    memcpy((uint8_t *)&g_net_info.ip6_gateway[0], &l_pu8_temp_buf, sizeof(g_net_info.ip6_gateway));

    // cmd/data port
    g_net_info.data_local_port = *((uint16_t *)&ini_net_info->data_local_port.v.i8);
    g_net_info.data_dest_port = *((uint16_t *)&ini_net_info->data_dest_port.v.i8);
    g_net_info.cmd_local_port = *((uint16_t *)&ini_net_info->cmd_local_port.v.i8);
    g_net_info.cmd_dest_port = *((uint16_t *)&ini_net_info->cmd_dest_port.v.i8);
    
    sscanf(ini_net_info->mac.v.s, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx", 
            &l_pu8_temp_buf[0], &l_pu8_temp_buf[1], &l_pu8_temp_buf[2], 
            &l_pu8_temp_buf[3], &l_pu8_temp_buf[4], &l_pu8_temp_buf[5]);
    memcpy((uint8_t *)&g_net_info.mac[0], &l_pu8_temp_buf, sizeof(g_net_info.mac));

    //protocol 0:ipv4, 1:ipv6
    g_net_info.data_protocol = ini_net_info->data_protocol.v.i8;
    g_net_info.cmd_protocol = ini_net_info->cmd_protocol.v.i8;

    // debug info
    #if ((0 < BSP_NET_DEBUG) || (0))
    uint8_t * l_pu8_buf = NULL;
    l_pu8_buf = (uint8_t *)&g_net_info.ip4_local_ip;
    printf("ip4_local_ip:%d.%d.%d.%d\n", l_pu8_buf[0],l_pu8_buf[1],l_pu8_buf[2],l_pu8_buf[3]);
    l_pu8_buf = (uint8_t *)&g_net_info.ip4_dest_ip;
    printf("ip4_dest_ip:%d.%d.%d.%d\n", l_pu8_buf[0],l_pu8_buf[1],l_pu8_buf[2],l_pu8_buf[3]);
    printf("ip4_mask:%d.%d.%d.%d\n", 
            g_net_info.ip4_mask[0], g_net_info.ip4_mask[1], 
            g_net_info.ip4_mask[2], g_net_info.ip4_mask[3]);
    printf("ip4_gateway:%d.%d.%d.%d\n", 
            g_net_info.ip4_gateway[0], g_net_info.ip4_gateway[1], 
            g_net_info.ip4_gateway[2], g_net_info.ip4_gateway[3]);

    // ipv6
    printf("ip6_local_ip:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", 
        g_net_info.ip6_local_ip[0], g_net_info.ip6_local_ip[1], g_net_info.ip6_local_ip[2],
        g_net_info.ip6_local_ip[3], g_net_info.ip6_local_ip[4], g_net_info.ip6_local_ip[5],
        g_net_info.ip6_local_ip[6], g_net_info.ip6_local_ip[7], g_net_info.ip6_local_ip[8],
        g_net_info.ip6_local_ip[9], g_net_info.ip6_local_ip[10], g_net_info.ip6_local_ip[11],
        g_net_info.ip6_local_ip[12], g_net_info.ip6_local_ip[13], g_net_info.ip6_local_ip[14],
        g_net_info.ip6_local_ip[15]);
    printf("ip6_global_ip:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", 
        g_net_info.ip6_global_ip[0], g_net_info.ip6_global_ip[1], g_net_info.ip6_global_ip[2],
        g_net_info.ip6_global_ip[3], g_net_info.ip6_global_ip[4], g_net_info.ip6_global_ip[5],
        g_net_info.ip6_global_ip[6], g_net_info.ip6_global_ip[7], g_net_info.ip6_global_ip[8],
        g_net_info.ip6_global_ip[9], g_net_info.ip6_global_ip[10], g_net_info.ip6_global_ip[11],
        g_net_info.ip6_global_ip[12], g_net_info.ip6_global_ip[13], g_net_info.ip6_global_ip[14],
        g_net_info.ip6_global_ip[15]);
    printf("ip6_dest_ip:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", 
        g_net_info.ip6_dest_ip[0], g_net_info.ip6_dest_ip[1], g_net_info.ip6_dest_ip[2],
        g_net_info.ip6_dest_ip[3], g_net_info.ip6_dest_ip[4], g_net_info.ip6_dest_ip[5],
        g_net_info.ip6_dest_ip[6], g_net_info.ip6_dest_ip[7], g_net_info.ip6_dest_ip[8],
        g_net_info.ip6_dest_ip[9], g_net_info.ip6_dest_ip[10], g_net_info.ip6_dest_ip[11],
        g_net_info.ip6_dest_ip[12], g_net_info.ip6_dest_ip[13], g_net_info.ip6_dest_ip[14],
        g_net_info.ip6_dest_ip[15]);
    printf("ip6_mask:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", 
        g_net_info.ip6_mask[0], g_net_info.ip6_mask[1], g_net_info.ip6_mask[2],
        g_net_info.ip6_mask[3], g_net_info.ip6_mask[4], g_net_info.ip6_mask[5],
        g_net_info.ip6_mask[6], g_net_info.ip6_mask[7], g_net_info.ip6_mask[8],
        g_net_info.ip6_mask[9], g_net_info.ip6_mask[10], g_net_info.ip6_mask[11],
        g_net_info.ip6_mask[12], g_net_info.ip6_mask[13], g_net_info.ip6_mask[14],
        g_net_info.ip6_mask[15]);
    printf("ip6_gateway:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", 
        g_net_info.ip6_gateway[0], g_net_info.ip6_gateway[1], g_net_info.ip6_gateway[2],
        g_net_info.ip6_gateway[3], g_net_info.ip6_gateway[4], g_net_info.ip6_gateway[5],
        g_net_info.ip6_gateway[6], g_net_info.ip6_gateway[7], g_net_info.ip6_gateway[8],
        g_net_info.ip6_gateway[9], g_net_info.ip6_gateway[10], g_net_info.ip6_gateway[11],
        g_net_info.ip6_gateway[12], g_net_info.ip6_gateway[13], g_net_info.ip6_gateway[14],
        g_net_info.ip6_gateway[15]);

    // cmd/data port
    printf("data_local_port:%d\n", g_net_info.data_local_port);
    printf("data_dest_port:%d\n", g_net_info.data_dest_port);
    printf("cmd_local_port:%d\n", g_net_info.cmd_local_port);
    printf("cmd_dest_port:%d\n", g_net_info.cmd_dest_port);
    printf("mac:%2x:%2x:%2x:%2x:%2x:%2x\n", 
            g_net_info.mac[0], g_net_info.mac[1], g_net_info.mac[2],
            g_net_info.mac[3], g_net_info.mac[4],g_net_info.mac[5]);
    #endif
    //
    error:
    RETURN_ERROR_CODE(l_u32_ret, __func__);
}
/**
 * @brief save param to ini file
 * 
 * @param ini_net_info ：ini网络参数信息结构体
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
uint32_t save_net_param_to_ini(ini_net_info_type *ini_net_info)
{
    uint8_t * l_pu8_temp = NULL;
    uint32_t l_u32_ret = 0;

    // ipv4
    /* 写入 ini_config */
    l_pu8_temp = (uint8_t *)&g_net_info.ip4_local_ip;
    sprintf(ini_net_info->ip4_local_ip.v.s, "%d.%d.%d.%d", l_pu8_temp[0], l_pu8_temp[1], l_pu8_temp[2], l_pu8_temp[3]);
    l_pu8_temp = (uint8_t *)&g_net_info.ip4_dest_ip;
    sprintf(ini_net_info->ip4_dest_ip.v.s, "%d.%d.%d.%d", l_pu8_temp[0], l_pu8_temp[1], l_pu8_temp[2], l_pu8_temp[3]);
    l_pu8_temp = g_net_info.ip4_mask;
    sprintf(ini_net_info->ip4_mask.v.s, "%d.%d.%d.%d", l_pu8_temp[0], l_pu8_temp[1], l_pu8_temp[2], l_pu8_temp[3]);
    l_pu8_temp = g_net_info.ip4_gateway;
    sprintf(ini_net_info->ip4_gateway.v.s, "%d.%d.%d.%d", l_pu8_temp[0], l_pu8_temp[1], l_pu8_temp[2], l_pu8_temp[3]);

    // ipv6
    l_pu8_temp = g_net_info.ip6_local_ip;
    sprintf(ini_net_info->ip_local_ipv6.v.s, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", 
            l_pu8_temp[0],l_pu8_temp[1],l_pu8_temp[2],l_pu8_temp[3],
            l_pu8_temp[4],l_pu8_temp[5],l_pu8_temp[6],l_pu8_temp[7],
            l_pu8_temp[8],l_pu8_temp[9],l_pu8_temp[10],l_pu8_temp[11],
            l_pu8_temp[12],l_pu8_temp[13],l_pu8_temp[14],l_pu8_temp[15]);

    l_pu8_temp = g_net_info.ip6_global_ip;
    sprintf(ini_net_info->ip_global_ipv6.v.s, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", 
            l_pu8_temp[0],l_pu8_temp[1],l_pu8_temp[2],l_pu8_temp[3],
            l_pu8_temp[4],l_pu8_temp[5],l_pu8_temp[6],l_pu8_temp[7],
            l_pu8_temp[8],l_pu8_temp[9],l_pu8_temp[10],l_pu8_temp[11],
            l_pu8_temp[12],l_pu8_temp[13],l_pu8_temp[14],l_pu8_temp[15]);

    l_pu8_temp = g_net_info.ip6_dest_ip;
    sprintf(ini_net_info->ip_ipv6.v.s, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", 
            l_pu8_temp[0],l_pu8_temp[1],l_pu8_temp[2],l_pu8_temp[3],
            l_pu8_temp[4],l_pu8_temp[5],l_pu8_temp[6],l_pu8_temp[7],
            l_pu8_temp[8],l_pu8_temp[9],l_pu8_temp[10],l_pu8_temp[11],
            l_pu8_temp[12],l_pu8_temp[13],l_pu8_temp[14],l_pu8_temp[15]);

    l_pu8_temp = g_net_info.ip6_mask;
    sprintf(ini_net_info->mask_ipv6.v.s, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", 
            l_pu8_temp[0],l_pu8_temp[1],l_pu8_temp[2],l_pu8_temp[3],
            l_pu8_temp[4],l_pu8_temp[5],l_pu8_temp[6],l_pu8_temp[7],
            l_pu8_temp[8],l_pu8_temp[9],l_pu8_temp[10],l_pu8_temp[11],
            l_pu8_temp[12],l_pu8_temp[13],l_pu8_temp[14],l_pu8_temp[15]);

    l_pu8_temp = g_net_info.ip6_gateway;
    sprintf(ini_net_info->gateway_ipv6.v.s, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", 
            l_pu8_temp[0],l_pu8_temp[1],l_pu8_temp[2],l_pu8_temp[3],
            l_pu8_temp[4],l_pu8_temp[5],l_pu8_temp[6],l_pu8_temp[7],
            l_pu8_temp[8],l_pu8_temp[9],l_pu8_temp[10],l_pu8_temp[11],
            l_pu8_temp[12],l_pu8_temp[13],l_pu8_temp[14],l_pu8_temp[15]);

    // cmd/data port
    *((uint16_t *)&ini_net_info->data_local_port.v.i8) = g_net_info.data_local_port;
    *((uint16_t *)&ini_net_info->data_dest_port.v.i8) = g_net_info.data_dest_port;
    *((uint16_t *)&ini_net_info->cmd_local_port.v.i8) = g_net_info.cmd_local_port;
    *((uint16_t *)&ini_net_info->cmd_dest_port.v.i8) = g_net_info.cmd_dest_port;
    l_pu8_temp = g_net_info.mac;
    sprintf(ini_net_info->mac.v.s, "%x:%x:%x:%x:%x:%x", 
                                    l_pu8_temp[0], l_pu8_temp[1], l_pu8_temp[2], 
                                    l_pu8_temp[3], l_pu8_temp[4], l_pu8_temp[5]);

    //protocol 0:ipv4, 1:ipv6
    ini_net_info->data_protocol.v.i8 = g_net_info.data_protocol;
    ini_net_info->cmd_protocol.v.i8 = g_net_info.cmd_protocol;

    // debug info
    #if ((0 < BSP_NET_DEBUG) || (0))
    printf("ip4_local_ip:%s\n", ini_net_info->ip4_local_ip.v.s);
    printf("ip4_dest_ip:%s\n", ini_net_info->ip4_dest_ip.v.s);
    printf("ip4_mask:%s\n", ini_net_info->ip4_mask.v.s);
    printf("ip4_gateway:%s\n", ini_net_info->ip4_gateway.v.s);

    // ipv6
    printf("ip_local_ipv6:%s\n", ini_net_info->ip_local_ipv6.v.s);
    printf("ip_global_ipv6:%s\n", ini_net_info->ip_global_ipv6.v.s);
    printf("ip_ipv6:%s\n", ini_net_info->ip_ipv6.v.s);
    printf("mask_ipv6:%s\n", ini_net_info->mask_ipv6.v.s);
    printf("gateway_ipv6:%s\n", ini_net_info->gateway_ipv6.v.s);

    // cmd/data port
    printf("data_local_port:%d\n", *(uint16_t *)&ini_net_info->data_local_port.v.i8);
    printf("data_dest_port:%d\n", *(uint16_t *)&ini_net_info->data_dest_port.v.i8);
    printf("cmd_local_port:%d\n", *(uint16_t *)&ini_net_info->cmd_local_port.v.i8);
    printf("cmd_dest_port:%d\n", *(uint16_t *)&ini_net_info->cmd_dest_port.v.i8);

    //protocol 0:ipv4, 1:ipv6
    printf("data_protocol:%d\n", ini_net_info->data_protocol.v.i8);
    printf("cmd_protocol:%d\n", ini_net_info->cmd_protocol.v.i8);
    #endif
    error:
    RETURN_ERROR_CODE(l_u32_ret, __func__);
}

/**
 * @brief net global variables param  init
 * 
 * @param None ：
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
static uint32_t ipv4_ipv6_ip_socket_init(uint8_t l_socket_type)
{
    uint32_t l_u32_ret = 0;
    uint8_t *l_u8_buf = NULL;
    struct in_addr *l_in_addr_ip = NULL;

    switch (l_socket_type)
    {
        case SOCKET_BROADCAST_TYPE:
        {
            /* broadcast socket */
            g_socket_info[l_socket_type].ip_protocol = g_net_info.cmd_protocol;
            g_socket_info[l_socket_type].socket_type = l_socket_type;
            g_socket_info[l_socket_type].local_ip_ipv4.s_addr = 0;
            g_socket_info[l_socket_type].dest_ip_ipv4.s_addr = 0; 
            g_socket_info[l_socket_type].local_port  = 6060;
            g_socket_info[l_socket_type].dest_port  = 0;
            break;
        }
        case SOCKET_CMD_TYPE:
        {
            /* cmd config socket */
            g_socket_info[l_socket_type].ip_protocol = g_net_info.cmd_protocol;
            g_socket_info[l_socket_type].socket_type = l_socket_type;
            g_socket_info[l_socket_type].local_ip_ipv4 = *(struct in_addr *)&g_net_info.ip4_local_ip;
            g_socket_info[l_socket_type].dest_ip_ipv4 = *(struct in_addr *)&g_net_info.ip4_dest_ip; 
            g_socket_info[l_socket_type].local_port  = g_net_info.cmd_local_port;
            g_socket_info[l_socket_type].dest_port  = g_net_info.cmd_dest_port;
            break;
        }
        case SOCKET_DATA_TYPE:
        {
            /* data config socket */
            break;
        }
        default:
            break;
    }

    /* debug info */
    #if ((BSP_NET_DEBUG > 0) || (0))
    {
        printf("[info]g_socket_info_ip_protocol:(%d), local_port:%d,dest_port%d\n", 
                        g_socket_info[SOCKET_CMD_TYPE].ip_protocol,
                        g_socket_info[SOCKET_CMD_TYPE].local_port,
                        g_socket_info[SOCKET_CMD_TYPE].dest_port);
    }
    #endif
    //

    error:
    RETURN_ERROR_CODE(l_u32_ret, __func__);
}
/**
 * @brief socket初始化
 * 
 * @param socket_info ：socket信息
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
static uint32_t socket_modules_init(socket_info_type * socket_info)
{
    uint32_t l_u32_ret = 0;
    uint32_t l_u32_recv_broadcast_enable = 1;    // 广播使能
    struct sockaddr_in l_sockaddr_in;

    /* IPV4 */
    if (socket_info->ip_protocol == IPV4_PROTOCOL)
    {
        /* 创建 IPv4 套接字 */
        socket_info->fd = socket(AF_INET, SOCK_DGRAM, 0);
        if (socket_info->fd < 0)
        {
            printf("create socket failed! socket_type:%d\n", socket_info->socket_type);
            SET_ERROR_CODE(l_u32_ret, 0);
            goto error;
        }
        else
        {
            printf("create udp socket ok, socket_info->fd = %d.\n", socket_info->fd);
        }
        

        /* 设置广播socket */
        if (socket_info->socket_type == SOCKET_BROADCAST_TYPE)
        {
            /* 设置socket广播使能 */
            if (0 != setsockopt(socket_info->fd, SOL_SOCKET, SO_BROADCAST, &l_u32_recv_broadcast_enable, sizeof(l_u32_recv_broadcast_enable)))
            {
                printf("set socket SO_BROADCAST error code!\n");
            }
            else
            {
                printf("set socket SO_BROADCAST ok!\n");
            }
            
        }
        
        // 设置发送缓冲区
        int send_buf_size = 1024 * 1024 * 8;     // 150KB
        if (setsockopt(socket_info->fd, SOL_SOCKET, SO_SNDBUF, &send_buf_size, sizeof(send_buf_size)) < 0) 
        {
            perror("setsockopt SO_SNDBUF failed");
        } 
        else 
        {
            // 验证实际设置值
            int actual_buf_size;
            socklen_t len = sizeof(actual_buf_size);
            getsockopt(socket_info->fd, SOL_SOCKET, SO_SNDBUF, &actual_buf_size, &len);
            printf("Actual send buffer size: %d bytes\n", actual_buf_size);
        }

        // 设置接收缓冲区
        int recv_buf_size = 1024 * 1024;    // 1MB
        if (setsockopt(socket_info->fd, SOL_SOCKET, SO_RCVBUF, &recv_buf_size, sizeof(recv_buf_size)) < 0) 
        {
            perror("setsockopt SO_RCVBUF failed");
        } 
        else 
        {
            // 验证实际缓冲区大小
            int actual_buf_size;
            socklen_t len = sizeof(actual_buf_size);
            getsockopt(socket_info->fd, SOL_SOCKET, SO_RCVBUF, &actual_buf_size, &len);
            printf("Actual recv buffer: %d bytes\n", actual_buf_size);
        }

        // 设置 IP_PKTINFO
        
        /* 设置local ip地址 and port */
        memset(&l_sockaddr_in, 0, sizeof(l_sockaddr_in));
        l_sockaddr_in.sin_family = AF_INET;
        l_sockaddr_in.sin_addr.s_addr = INADDR_ANY;
        l_sockaddr_in.sin_port = htons(socket_info->local_port);
        // memcpy(&l_sockaddr_in.sin_addr, &socket_info->local_ip_ipv4, sizeof(l_sockaddr_in.sin_addr));

        /* 将套接字绑定到本地地址 */
        if (bind(socket_info->fd, (const struct sockaddr *)&l_sockaddr_in, sizeof(l_sockaddr_in)) != 0) 
        {
            printf("bind failed\n");
            SET_ERROR_CODE(l_u32_ret, 1);
            goto error;
        }
        
        // 清空地址结构体变量
        memset(&l_sockaddr_in, 0x00, sizeof(l_sockaddr_in));

        // 配置目标ip
        l_sockaddr_in.sin_family = AF_INET;
        l_sockaddr_in.sin_port = htons(socket_info->dest_port);
        memcpy(&l_sockaddr_in.sin_addr, &socket_info->dest_ip_ipv4, sizeof(l_sockaddr_in.sin_addr));
        
        /* 及连接dest ip地址 and port */
        if (socket_info->dest_port != 0)
        {
            if (connect(socket_info->fd, (struct sockaddr *)&l_sockaddr_in, sizeof(l_sockaddr_in)) != 0)
            {
                printf("connect failed!\n");
                SET_ERROR_CODE(l_u32_ret, 2);
                goto error;
            }
        }
    }
    else    // IPV6
    {
        SET_ERROR_CODE(l_u32_ret, 3);
    }

    //
    #if((BSP_NET_DEBUG > 0) || (0))
    printf("dest_port:%d\n",l_sockaddr_in.sin_port);
    #endif
    // 


    RETURN_ERROR_CODE(l_u32_ret, __func__);
    error:
    // 关闭套接字
    close(socket_info->fd);
    RETURN_ERROR_CODE(l_u32_ret, __func__);
}
/**
 * @brief udp 发送函数
 * 
 * @param send_buf ：发送缓存
 * @param send_len ：发送字节数
 * @param sockaddr ：目标地址信息
 * @param socket_flag ：端口标志
 * 
 * @return uint32_t ：0：正常，非0：错误代码
 * 
 * @note：
 */
uint32_t net_send_udp_data(uint8_t *send_buf, uint32_t send_len, struct sockaddr * sockaddr, uint32_t socket_flag)
{
    uint32_t l_u32_ret = 0;
    int l_i32_error = 0;

    /* 申请互斥锁 */
    pthread_mutex_lock(&g_net_send_semaphore);

    /* 发送数据 */
    switch (socket_flag)
    {
        case SOCKET_BROADCAST_TYPE:
        {
            if (sockaddr != NULL)    // 使用广播时目标主机ip sockaddr不为空
            {
                l_i32_error = sendto(g_socket_info[socket_flag].fd, send_buf, send_len, 0, sockaddr, sizeof(struct sockaddr));
                if (send_len > l_i32_error)
                {
                    printf("sendto failed, error:%d\n", l_i32_error);
                    SET_ERROR_CODE(l_u32_ret, 0);
                    goto error;
                }
            }
            break;
        }
        case SOCKET_CMD_TYPE:
        case SOCKET_DATA_TYPE:
        {
            // send_len = 100;   // udp数据包极限大小为65507
            // printf("udp data len is %u.\n", send_len);
            l_i32_error = send(g_socket_info[socket_flag].fd, send_buf, send_len, 0);
            if (l_i32_error == -1)
            {
                printf("sendto failed, error:%d, g_socket_info[socket_flag].fd = %d\n", l_i32_error, g_socket_info[socket_flag].fd);
                SET_ERROR_CODE(l_u32_ret, 1);
                goto error;
            }
            // else
            // {
            //     printf("sendto %d Byte udp data ok.\n", l_i32_error);
            // }
            thread_uSleep(200); // 适当增加延时，避免丢包
            break;
        }
        default:
            break;
    }

    error:
    /* 释放互斥锁 */
    pthread_mutex_unlock(&g_net_send_semaphore);
    RETURN_ERROR_CODE(l_u32_ret, __func__);
}
